package brc.syntacticTree;

import java.io.IOException;
import java.io.Writer;
import java.util.List;

public class FunctionCallNode implements TypedTreeNode {
	/**
	 * 
	 */
	private static final long serialVersionUID = 3227915509642730954L;
	public final String EXIBE_COMANDO = "exibe";
	public final String LEIA_NUMERO_COMANDO = "leiaNumero";
	public final String LEIA_TEXTO_COMANDO = "leiaTexto";
	
	private String functionName;
	private List<TypedTreeNode> parameters; 
	
	public FunctionCallNode(String functionName, List<TypedTreeNode> params) {
		if (functionName == null) {
			throw new NullPointerException("A function call must have a name");
		}
		this.functionName = functionName;
		this.parameters = params;
	}
	
	public String getFunctionName() {
		return functionName;
	}
	public List<TypedTreeNode> getParameters() {
		return parameters;
	}

	@Override
	public void writeAssembly(Writer writer) throws IOException {
		if (this.functionName.equals(EXIBE_COMANDO) ||
			this.functionName.equals(LEIA_NUMERO_COMANDO) ||
			this.functionName.equals(LEIA_TEXTO_COMANDO)) {
			writer.write("getstatic java/lang/System/out Ljava/io/PrintStream;\r\n");
			// coloca o elemento da pilha
			this.parameters.get(0).writeAssembly(writer);
			int paramType = this.parameters.get(0).getType();
			
			if (paramType == TypedTreeNode.TIPO_NUMERO) {
				writer.write("invokevirtual java/io/PrintStream/println(I)V\r\n");
			}
			else if (paramType == TypedTreeNode.TIPO_TEXTO){
				writer.write("invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V\r\n");
			}
		}
		if (this.functionName.equals(LEIA_NUMERO_COMANDO)) {
			writer.write("new java/util/Scanner\r\n");
			writer.write("dup\r\n");
			writer.write("getstatic java/lang/System/in Ljava/io/InputStream;\r\n");
			writer.write("invokespecial java/util/Scanner/<init>(Ljava/io/InputStream;)V\r\n");
			writer.write("invokevirtual java/util/Scanner/nextInt()I\r\n");
		}
		else if (this.functionName.equals(LEIA_TEXTO_COMANDO)) {
			writer.write("new java/util/Scanner\r\n");
			writer.write("dup\r\n");
			writer.write("getstatic java/lang/System/in Ljava/io/InputStream;\r\n");
			writer.write("invokespecial java/util/Scanner/<init>(Ljava/io/InputStream;)V\r\n");
			writer.write("invokevirtual java/util/Scanner/nextLine()Ljava/lang/String;\r\n");	
		}
	}

	@Override
	public void semanticCheck() throws SemanticException {
		if (this.functionName.equals(EXIBE_COMANDO)) {
			if (this.parameters.size() != 1) {
				throw new SemanticException("Exibe function parameter count mismatch");
			}
		}
		else if (this.functionName.equals(LEIA_NUMERO_COMANDO) || this.functionName.equals(LEIA_TEXTO_COMANDO)) {
			if (this.parameters.size() != 1) {
				throw new SemanticException("Leia function parameter count mismatch");
			}
		}
		else {
			throw new SemanticException("Not supported function name");
		}
		for (TypedTreeNode node : this.parameters) {
			node.semanticCheck();
		}
	}

	@Override
	public int getType() {
		if (this.functionName.equals(LEIA_NUMERO_COMANDO)){
			return TypedTreeNode.TIPO_NUMERO;
		}
		else if (this.functionName.equals(LEIA_TEXTO_COMANDO)) {
			return TypedTreeNode.TIPO_TEXTO;
		}
		else {
			return 0;
		}
	}

}
